home *** CD-ROM | disk | FTP | other *** search
- #include "WhiteCap.h"
-
- #include "EgOSUtils.h"
-
- #if EG_MAC
- #include <Menus.h>
- #include <Windows.h>
- #include <Palettes.h>
-
- #if MACAMP
- #include "MacAMP_Visual.h"
- extern VPInfoBlock gPlugInfo;
- #endif
-
-
- #if SOUNDJAM
- #include "VisFramework.h"
- #endif
-
-
- #include "CEgFileSpec.h"
- #include "Sample.h"
- #include "CEgIOFile.h"
-
-
- #define __setupPort GDHandle saveDev; \
- GrafPtr savePort; \
- ::GetGWorld( (GWorldPtr*)(&savePort), &saveDev ); \
- ::SetPort( mOSPort );
-
-
- #define __restorePort ::SetGWorld( (GWorldPtr)(savePort), saveDev );
- #endif
-
- #if EG_WIN
- #define __setupPort
- #define __restorePort
- #include "RectUtils.h"
-
- #include "vis.h"
- extern winampVisModule gWCModule;
-
- #endif
-
-
-
- WhiteCap::WhiteCap( CEgFileSpec& inPluginsFolder, void* inRefCon ) :
- mPrefs( "WhiteCap Preferences", true ),
- mConfigs( cNoDuplicates_CaseInsensitive, cSortLowToHigh) {
- CEgFileSpec spec;
- UtilStr name, str;
-
-
- mPrefs.Load();
- if ( mPrefs.GetPref( 'Vers' ) != 304 ) {
- mTransitionLo = 4;
- mTransitionHi = 15;
- mSlideShowInterval = 20000; // Factory: 20 secs per config
- mScrnSaverDelay = 15 * 60000; // Factory: 15 mins before screen saver kicks in
- }
- else {
- mTransitionLo = mPrefs.GetPref( 'TrLo' );
- mTransitionHi = mPrefs.GetPref( 'TrHi' );
- mSlideShowInterval = mPrefs.GetPref( 'Slde' ) * 1000;
- mScrnSaverDelay = mPrefs.GetPref( 'SSvr' ) * 1000 * 60;
- }
-
- mRefCon = inRefCon;
- mInSlideShowMode = true;
- mAtFullScreen = false;
- mOSPort = NULL;
- mNumWorlds = 0;
- mFrameCount = 0;
- mFrameCountStart = EgOSUtils::CurTimeMS();
- mCurConfigNum = -1;
- mNextShapeChange = 0x7FFFFFFF;
- mFramesPer10Secs = 400;
- mDoingSetPortWin = false;
- mMouseWillAwaken = false;
-
- if ( mSlideShowInterval > 0 )
- mNextShapeChange = mFrameCountStart + mSlideShowInterval;
-
- BuildConfigList( inPluginsFolder );
- }
-
-
-
-
- WhiteCap::~WhiteCap() {
-
-
- SetFullScreen( false );
-
- // Rewrite the prefs to disk...
- mPrefs.SetPref( 'Vers', 304 );
- mPrefs.SetPref( 'Slde', mSlideShowInterval / 1000 );
- mPrefs.SetPref( 'SSvr', mScrnSaverDelay / 60000 );
- mPrefs.SetPref( 'TrHi', mTransitionHi );
- mPrefs.SetPref( 'TrLo', mTransitionLo );
-
- #if MACAMP || WINAMP
- Rect r;
- #if MACAMP
- GetWinRect( r );
- #else
- // Very annoying: in Win32, the call to GetWindowRect() is returning garbage in ~WhiteCap(), so just
- // forget about saving the window position for now in windows :_(
- r = mWinRectHolder;
- #endif
- mPrefs.SetPref( 'wTop', r.top );
- mPrefs.SetPref( 'wLft', r.left );
- mPrefs.SetPref( 'wBot', r.bottom );
- mPrefs.SetPref( 'wRgt', r.right );
- #endif
-
- mPrefs.Store();
-
-
- // Delete all the existing worlds
- for ( int i = 0; i < mNumWorlds; i++ )
- delete mWorld[ i ];
-
-
- #if DATA_DUMP
- CEgIOFile oFile;
- CEgFileSpec spec( "WhiteCap Dump" );
-
- oFile.open( &spec );
- if ( oFile.noErr() ) {
- oFile.Write( &mDumpData );
- }
- #endif
- }
-
-
-
-
-
- bool WhiteCap::PtInTitle( Point inPt ) {
- int i;
-
- Rect r;
- GetWinRect( r );
-
- inPt.v -= r.top;
- inPt.h -= r.left;
-
- for ( i = 0; i < mNumWorlds; i++ ) {
- if ( ::PtInRect( inPt, &mWorld[ i ] -> mTitleRect ) )
- return true;
- }
-
- return false;
- }
-
-
-
-
- void WhiteCap::SelectConfig() {
- long i, sel, idxOffset;
- Point pt;
- UtilStr name;
-
- EgOSUtils::GetMouse( pt );
-
- // We want to add the menu item "(Start Slide Show)" when we're not in slide show mode
- if ( mInSlideShowMode )
- idxOffset = 0;
- else
- idxOffset = 1;
-
- // If we're in full screen mode, show the mouse ptr
- if ( mAtFullScreen )
- EgOSUtils::ShowCursor();
-
- #if EG_MAC
- MenuHandle menu;
-
- __setupPort
-
- // If we found a world, show a popup menu to select from the configs
- menu = ::NewMenu( 123, "\p " );
- if ( ! mInSlideShowMode ) {
- ::AppendMenu( menu, "\p " );
- ::SetMenuItemText( menu, 1, "\p(Start Slide Show)" );
- }
- for ( i = 1; mConfigs.FetchSpecName( i, name ); i++ ) {
- ::AppendMenu( menu, "\p " );
- ::SetMenuItemText( menu, i + idxOffset, name.getPasStr() );
- }
- ::CheckItem( menu, mCurConfigNum + idxOffset, true );
- ::InsertMenu( menu, -1 );
- sel = ::PopUpMenuSelect( menu, pt.v - 6, pt.h, mCurConfigNum + idxOffset );
- ::DeleteMenu( 123 );
- ::DisposeMenu( menu );
-
- sel = ( sel & 0xFFFF0000 ) ? (sel & 0xFFFF) : 0;
- #endif
-
-
- #if EG_WIN
- long flags;
-
- HMENU myMenu = ::CreatePopupMenu();
- if ( ! mInSlideShowMode )
- ::AppendMenu( myMenu, MF_ENABLED | MF_STRING, 1, "(Start Slide Show)" );
- for ( i = 1; mConfigs.FetchSpecName( i, name ); i++ ) {
- flags = MF_ENABLED | MF_STRING;
- if ( mCurConfigNum == i )
- flags |= MF_CHECKED;
- ::AppendMenu( myMenu, flags, i + idxOffset, name.getCStr() );
- }
- sel = ::TrackPopupMenuEx( myMenu, TPM_RETURNCMD, pt.h, pt.v, mOSPort, NULL );
- ::DestroyMenu( myMenu );
- if ( mAtFullScreen )
- ::SetCapture( mOSPort );
- #endif
-
- if ( sel > 0 ) {
- if ( mInSlideShowMode )
- mInSlideShowMode = false;
- else {
- if ( sel == 1 ) {
- mInSlideShowMode = true;
- mConfigPlayList.Randomize();
- sel = mConfigPlayList.Fetch( 1 ); }
- else
- sel--;
- }
-
- LoadConfig( sel );
- }
-
- __restorePort
- }
-
-
-
-
-
-
-
-
-
- void WhiteCap::SetFullScreen( bool inFullScreen ) {
-
- #if SOUNDJAM
- VisHandlerData* handlerData = (VisHandlerData*) mRefCon;
- if ( handlerData ) {
- if ( mAtFullScreen != inFullScreen ) {
- if ( PlayerSetFullScreen(handlerData->appCookie, handlerData->playerProc, inFullScreen) == noErr)
- mAtFullScreen = inFullScreen;
- }
- }
- #else
-
-
- bool ok;
- int dispNum;
- Point size;
-
- if ( inFullScreen && ! mAtFullScreen ) {
-
- if ( PixPort::FullscreenAvail() ) {
-
-
- __setupPort
-
- // Update the positon of our win
- GetWinRect( mWinRectHolder );
- dispNum = PixPort::GetOwningDisplay( *((Point*) &mWinRectHolder) );
-
- #if MACAMP
- if ( gPlugInfo.ma -> EnterFullScreen )
- gPlugInfo.ma -> EnterFullScreen( cPluginAuthor, cWhiteCapID );
- ::HideWindow( mOSPort );
- #endif
-
- #if WINAMP
- ::ShowWindow( gWCModule.hwndParent, SW_HIDE | SW_MINIMIZE );
- #endif
-
- // Put in pref wheather to try 32 before 16 bit color?
- ok = mPort.InitFullscreen( dispNum, size, mOSPort );
-
- if ( ok ) {
-
-
- mDispRect.left = 0;
- mDispRect.top = 0;
- mDispRect.right = size.h;
- mDispRect.bottom = size.v;
- ResizeWorlds();
- mAtFullScreen = true;
- mFullscreenStartTime = EgOSUtils::CurTimeMS();
-
- // If we don't expire them, there'll be an ugly gap for the time it took to go fullscreen
- for ( int i = 0; i < mNumWorlds; i++ )
- mWorld[ i ] -> ExpireSamples();
- }
- else {
- #if MACAMP
- if ( gPlugInfo.ma -> ExitFullScreen )
- gPlugInfo.ma -> ExitFullScreen();
- ::ShowWindow( mOSPort );
- #endif
-
- #if WINAMP
- ::ShowWindow( gWCModule.hwndParent, SW_SHOWNORMAL );
- #endif
- }
-
- __restorePort
- } }
- else if ( ! inFullScreen && mAtFullScreen ) {
-
-
- // Restore the window
- mPort.Deactivate();
-
- #if MACAMP
- if ( gPlugInfo.ma -> ExitFullScreen )
- gPlugInfo.ma -> ExitFullScreen();
- #endif
-
- __setupPort
-
- SetWinPort( mOSPort, &mWinRectHolder );
-
- __restorePort
-
- mLastMousePt.h -= 55;
- mAtFullScreen = false;
-
- #if WINAMP
- ::ShowWindow( gWCModule.hwndParent, SW_SHOWNORMAL );
- #endif
-
- }
- #endif
-
- if ( inFullScreen ) {
-
- // Changing the port (and the resolution) may change the mouse cords
- EgOSUtils::GetMouse( mLastMousePt );
-
- // Default: mouse movement will not exit fullscreen mode
- mMouseWillAwaken = false;
- }
-
- #if EG_MAC
- ::FlushEvents( 0xFFFF, 0 );
- #endif
- }
-
-
-
- void WhiteCap::GetWinRect( Rect& outRect ) {
-
- if ( mOSPort ) {
-
- #if EG_MAC
- outRect = (**(((CGrafPtr) mOSPort)->portPixMap)).bounds;
- outRect.left *= -1;
- outRect.top *= -1;
- outRect.right = outRect.left + mOSPort -> portRect.right;
- outRect.bottom = outRect.top + mOSPort -> portRect.bottom;
- #elif EG_WIN
- RECT wr;
- ::GetWindowRect( mOSPort, &wr );
-
- outRect.left = wr.left;
- outRect.top = wr.top;
- outRect.right = wr.right;
- outRect.bottom = wr.bottom;
- #endif
- }
- else
- SetRect( &outRect, 0, 0, 0, 0 );
- }
-
-
- void WhiteCap::RecordSample( long inCurTime, float inSpectrum[] ) {
-
- #if DATA_DUMP
- mDumpData.Append( &inCurTime, 4 );
- mDumpData.Append( inSpectrum, sizeof( float ) * NUM_SAMPLE_BINS );
-
- // Give the sample data to the window if we're not just dumping the sound data
- #else
-
- // Loop thru all the panes in the window
- for ( int i = 0; i < mNumWorlds; i++ ) {
-
- // Tell the world to take a new sound sample (if it wants)
- mWorld[ i ] -> RecordSample( inCurTime, inSpectrum );
- }
- #endif
- }
-
-
-
-
-
-
-
-
- void WhiteCap::Draw() {
- Rect r;
- Point pt;
- long i, time = EgOSUtils::CurTimeMS();
-
-
- // Load a random waveshape every so often, and randomize things
- if ( time > mNextShapeChange && mInSlideShowMode ) {
-
- // Load the next config in the (randomized) config list...
- i = mConfigPlayList.FindIndexOf( mCurConfigNum );
-
- // Make a new play list if we've reached the end of the list...
- if ( i >= mConfigPlayList.Count() ) {
- mConfigPlayList.Randomize();
- i = 0;
- }
- LoadConfig( mConfigPlayList.Fetch( i + 1 ) );
- }
-
-
- EgOSUtils::GetMouse( pt );
-
- // Check the mouse pos and record it as active if its been moved.
- if ( pt.h != mLastMousePt.h || pt.v != mLastMousePt.v ) {
- mLastMousePt = pt;
- mLastActiveTime = time;
- if ( mAtFullScreen && mMouseWillAwaken )
- SetFullScreen( false );
- }
-
- // If we've been idle for too long, go into full screen mode and let mouse movement wake us
- if ( time - mLastActiveTime > mScrnSaverDelay && mScrnSaverDelay > 0 ) {
- mLastActiveTime = time;
- SetFullScreen( true );
- mMouseWillAwaken = true;
- }
-
- __setupPort
-
- // Tell the PixPort we're about to start accessing it big time
- mPort.BeginFrame();
-
- // Loop thru all the panes in the window and the the whitecap wave thingy
- time = EgOSUtils::CurTimeMS();
- for ( i = 0; i < mNumWorlds; i++ ) {
-
- // Tell the world to update itself to the offscreen draw port
- mWorld[ i ] -> Render( time, mPort, r );
-
- // If we're drawing to a window, draw it right away
- if ( mPort.IsFullscreen() )
- mPort.UnionDirtyRect( &r );
- else
- mPort.CopyBits( mOSPort, &r, &r );
- }
-
-
- // In the case we're using DrawSpocks, the cur port is the 'screen' port
- GrafPtr port = mOSPort;
- #if EG_MAC
- if ( mPort.IsFullscreen() )
- ::GetPort( &port );
- #endif
-
- // For each pane/world, draw the title string...
- for ( i = 0; i < mNumWorlds; i++ ) {
-
- mWorld[ i ] -> DrawConfigName( port );
-
- // In mac land, we may need to tell the port to refresh the given rect on the screen
- #if EG_MAC
- mPort.UnionDirtyRect( &mWorld[ i ] -> mTitleRect );
- #endif
- }
-
-
- //__setupPort
-
- #if EG_MAC
-
- // If the option key is down, show the frame rate
- unsigned char km[16];
- ::GetKeys( (unsigned long*) km );
- i = 58;
- if ( ((km[ i >> 3 ] >> (i & 7)) & 1) != 0 ) {
-
- // Calc frame rate, show the current computation for frames
- if ( time - mFrameCountStart >= 1500 ) {
- mFramesPer10Secs = 10000 * mFrameCount / ( time - mFrameCountStart );
- mFrameRate.Assign( mFramesPer10Secs );
- mFrameRate.Insert( mFrameRate.length() - 1, ".", 1 );
- mFrameCountStart = time;
- mFrameCount = 0;
- }
- mFrameCount++;
-
- Rect r = { 0, 0, 20, 40 };
- ::EraseRect( &r );
- ::MoveTo( 5, 15 );
- ::DrawString( mFrameRate.getPasStr() );
- if ( mPort.IsFullscreen() )
- mPort.UnionDirtyRect( &r );
- }
- #endif
-
-
- mPort.EndFrame();
-
- __restorePort
-
- }
-
-
-
-
-
-
-
-
-
-
- #define ___max( a, b ) (( (a) > (b) ) ? (a) : (b))
- #define ___maxSide( r ) (___max( r.right - r.left, r.bottom - r.top ))
-
-
- void WhiteCap::SetWinPort( GrafPtr inWin, const Rect* inRect ) {
- Rect r;
-
- // mDoingSetPortWin == true is a signal that another thread is in SetWinPort()
- if ( mDoingSetPortWin )
- return;
- mDoingSetPortWin = true;
-
- if ( inRect )
- r = *inRect;
-
- // If an invalid win rect, fix it, you monkey!
- if ( r.right - r.left < 20 || r.bottom - r.top < 20 || ! inRect ) {
-
- r.top = mPrefs.GetPref( 'wTop' );
- r.left = mPrefs.GetPref( 'wLft' );
- r.right = mPrefs.GetPref( 'wRgt' );
- r.bottom = mPrefs.GetPref( 'wBot' );
-
- #if EG_MAC
- // Invalidate the window if it's offscreen...
- RgnHandle deskRgn = ::GetGrayRgn();
- ::SectRect( &(*deskRgn) -> rgnBBox, &r, &r );
- #endif
- }
-
- // If no prefs avail (or an older version, use factory rect) or a bad win, hard code a size
- if ( mPrefs.GetPref( 'Vers' ) != 30 || r.right - r.left < 20 || r.bottom - r.top < 20 ) {
- r.top = 50;
- r.left = 15;
- r.right = 480;
- r.bottom = 380;
- }
-
- long x = r.right - r.left;
- long y = r.bottom - r.top;
-
-
- #if EG_MAC
- ::MoveWindow( inWin, r.left, r.top, true );
- ::SizeWindow( inWin, x, y, true );
- ::ShowWindow( inWin );
- #else
- RECT cr;
-
- // Resize the window and find the rgn we have to work with
- ::MoveWindow( inWin, r.left, r.top, x, y, false );
- ::GetClientRect( inWin, &cr );
- x = cr.right - cr.left;
- y = cr.bottom - cr.top;
- #endif
-
- // The playpen for WhiteCap will be the entire window client rgn (what we'll give SetPort)
- Rect portRect;
- ::SetRect( &portRect, 0, 0, x, y );
- SetPort( inWin, portRect, false );
-
- // Signal that this thread is done with SetPortWin()
- mDoingSetPortWin = false;
- }
-
-
-
-
-
- void WhiteCap::SetPort( GrafPtr inPort, const Rect& inRect, bool inFullScreen ) {
- long x = inRect.right - inRect.left;
- long y = inRect.bottom - inRect.top;
-
- mOSPort = inPort;
- mPort.Init( x, y );
- mDispRect = inRect;
- mAtFullScreen = inFullScreen;
-
- __setupPort
-
-
- // If we're brand spankin new, show at least 1 config, you monkey
- if ( mNumWorlds == 0 )
- LoadConfig( mCurConfigNum );
-
- __restorePort
-
- for ( int i = 0; i < mNumWorlds; i++ )
- mWorld[ i ] -> ExpireSamples();
-
- ResizeWorlds();
- }
-
-
-
-
- void WhiteCap::ResizeWorlds() {
- Rect r;
- long i, j, bestLen, cutLen, best;
-
-
- // Resize the panes in this window...
- mWorld[ 0 ] -> SetPaneRect( mDispRect );
- for ( i = 1; i < mNumWorlds; i++ ) {
-
- // Find the best world to cut in half
- for ( bestLen = -1, j = 0; j < i; j++ ) {
- cutLen = ___maxSide( (*mWorld[ j ] -> PaneRect()) );
- if ( cutLen >= bestLen ) {
- bestLen = cutLen;
- best = j;
- }
- }
-
- // Change the pane rect of both the unplaced world and the world that's about to get cut in half
- r = *(mWorld[ best ] -> PaneRect());
- if ( r.right - r.left == bestLen ) {
- r.right -= bestLen / 2;
- mWorld[ best ] -> SetPaneRect( r );
- OffsetRect( &r, bestLen / 2, 0 );
- mWorld[ i ] -> SetPaneRect( r ); }
- else {
- r.bottom -= bestLen / 2;
- mWorld[ best ] -> SetPaneRect( r );
- OffsetRect( &r, 0, bestLen / 2 );
- mWorld[ i ] -> SetPaneRect( r );
- }
- }
- }
-
-
-
-
-
-
-
-
-
- void WhiteCap::RefreshRect( const Rect& inUpdate ) {
-
- for ( int i = 0; i < mNumWorlds; i++ ) {
- mWorld[ i ] -> RefreshRect( inUpdate );
- }
- }
-
-
-
-
-
-
-
- void WhiteCap::LoadConfig( int inConfigNum ) {
- const CEgFileSpec* configSpec;
- int i, exists;
- long oldNumWorlds = mNumWorlds;
- long transitionTime = EgOSUtils::Rnd( mTransitionLo * 1000, mTransitionHi * 1000 );
-
-
- mNumWorlds = 0;
- mCurConfigNum = -1;
-
- // Fetch the spec for our config file or folder
- configSpec = mConfigs.FetchSpec( inConfigNum );
-
- if ( configSpec ) {
-
- // If we have a folder or file...
- exists = configSpec -> Exists();
- if ( exists == 2 ) {
- CEgFileSpec spec;
-
- bool startOver = true;
- while ( EgOSUtils::GetNextFile( *configSpec, spec, startOver, false ) ) {
- if ( mNumWorlds >= oldNumWorlds )
- mWorld[ mNumWorlds ] = new WhiteCapWorld;
- mWorld[ mNumWorlds ] -> Init( &spec, transitionTime );
- mNumWorlds++;
- startOver = false;
- }
- }
-
- // Know what to put a check mark next to in the popup menu
- mCurConfigNum = inConfigNum;
- }
-
- // If it's only one config file or there's no spec specifed
- if ( mNumWorlds == 0 ) {
- mNumWorlds = 1;
- if ( mNumWorlds > oldNumWorlds )
- mWorld[ 0 ] = new WhiteCapWorld;
- mWorld[ 0 ] -> Init( configSpec, transitionTime );
- }
-
- for ( i = mNumWorlds; i < oldNumWorlds; i++ )
- delete mWorld[ i ];
-
-
- // If the cursor was spun, init it back to the ptr
- EgOSUtils::ResetCursor();
-
- // Make sure all WhiteCap's configs live happily inside the allowed draw area
- ResizeWorlds();
-
- // Set the time for when we load a random config automatically
- mNextShapeChange = EgOSUtils::CurTimeMS() + mSlideShowInterval + transitionTime;
-
- // Very annoying: in Win32, the call to GetWindowRect() is returning garbage in ~WhiteCap(), so just
- // forget about saving the window position for now in windows :_(
- #if EG_WIN
- if ( ! mAtFullScreen )
- GetWinRect( mWinRectHolder );
- #endif
-
- if ( mAtFullScreen )
- EgOSUtils::HideCursor();
- }
-
-
-
-
- void WhiteCap::BuildConfigList( CEgFileSpec& inPluginsFolder ) {
- CEgFileSpec spec;
- bool startOver = true;
- int i;
-
- while ( EgOSUtils::GetNextFile( inPluginsFolder, spec, startOver, false ) ) {
- mConfigs.AddCopy( spec );
- startOver = false;
- }
-
- startOver = true;
- while ( EgOSUtils::GetNextFile( inPluginsFolder, spec, startOver, true ) ) {
- mConfigs.AddCopy( spec );
- startOver = false;
- }
-
- // Always have a item called (Default) in the config list
- UtilStr def( "(Default)" );
- spec.Assign( inPluginsFolder );
- if ( ! mConfigs.Lookup( def ) ) {
- spec.Rename( def );
- mConfigs.AddCopy( spec );
- }
- mCurConfigNum = mConfigs.Lookup( def );
-
- // Build a random config 'play' list
- mConfigPlayList.RemoveAll();
- for ( i = mConfigs.Count(); i > 0; i-- )
- mConfigPlayList.Add( i );
- mConfigPlayList.Randomize();
- }
-
-
-
-